#include "exchange_stl.h"
#include "topology/TopoBuilder.hpp"
#include "topology/TopoCompound.hpp"
#include "topomesh/BRepMeshIncrementalMesh.hpp"
#include "io/STLTool.hpp"
#include "common/system_log.h"
#include "utils/file_util.h"
#include "ExchangeTopoShape.h"

AMCAX_EXCHANGE_NAMESPACE_BEGIN

void ExchangeStl::ReadFromFilePath() 
{
    throw std::runtime_error("unsupport");
}

void ExchangeStl::ReadFromFileStream()
{
    throw std::runtime_error("unsupport");
}
// void ExchangeStl::Read()
// {
//     throw std::runtime_error("unsupport");
// }

void ExchangeStl::Write(const std::vector<std::shared_ptr<ExchangeObject>>& exchange_shapes, const std::shared_ptr<ExchangeDocumentInstance> &exchangeDocumentInstance)
{
#ifdef AMCAX_STL_ENABLE
    StlOutputParameter *parameter = dynamic_cast<StlOutputParameter *>(GetExchangeParameter()) ;
    double linearDeflection = DEFAULT_LINEAR_DEFLECTION ;
    double angleDeflection = DEFAULT_ANGLE_DEFLECTION ;
    if (nullptr != parameter) {
        linearDeflection = parameter->GetLinearDeflection();
        linearDeflection = (linearDeflection > MAX_LINEAR_DEFLECTION)? MAX_LINEAR_DEFLECTION : linearDeflection ;
        linearDeflection = (linearDeflection < MIN_LINEAR_DEFLECTION)? MIN_LINEAR_DEFLECTION : linearDeflection ;

        angleDeflection = parameter->GetAngleDeflection();
        angleDeflection = (angleDeflection > MAX_LINEAR_DEFLECTION)? MAX_ANGLE_DEFLECTION : angleDeflection ;
        angleDeflection = (angleDeflection < MIN_LINEAR_DEFLECTION)? MIN_ANGLE_DEFLECTION : angleDeflection ;
    }
    LOG_INFO("linearDeflection:{}",linearDeflection) ;
    
    AMCAX::TopoBuilder builder;
    AMCAX::TopoCompound comp;
    builder.MakeCompound(comp);

    std::vector<std::shared_ptr<ExchangeObject>> flatShapes;
    NestedExchangeShapeToFlat(flatShapes, exchange_shapes); 
    
    for (auto exData : flatShapes) 
    {
        if (!exData->shape->GetShape().IsNull())
        {
            // builder.Add(comp, exData->shape);
            LOG_INFO("meshing") ;
            AMCAX::BRepMeshIncrementalMesh aMesh(exData->shape->GetShape(), linearDeflection, true, angleDeflection);
            builder.Add(comp, exData->shape->GetShape());
        }
    }
    LOG_INFO("meshing done") ;
    // AMCAX::TopoShape poundShape = comp;
    // AMCAX::BRepMeshIncrementalMesh aMesh(poundShape, linearDeflection, true, angleDeflection);
    
    if (OUTPUT_FILE_TYPE::FILE_PATH == outputFileType_) {
        if (AMCAX::Exchange::file_util::is_file_exist(filePath_))
        {
            LOG_ERROR("file<{}> already exist",filePath_) ;
            return ;
        }
       AMCAX::STLTool::WriteShape(comp, filePath_);
    }
    else if (OUTPUT_FILE_TYPE::FILE_OUTPUT_STREAM == outputFileType_) 
    {
        if(nullptr == outFileStream_) {
            LOG_ERROR("outFileStream_ is null") ;
            return  ;
        }
        // AMCAX::STLTool::WriteShape(poundShape, *outFileStream_);
    }else {
        LOG_ERROR("output file type:{} is unknown",(int)outputFileType_) ;
        return ;
    }
    
    // AMCAX::STLTool::WriteShape(poundShape, filePath_);
#endif
}


AMCAX_EXCHANGE_NAMESPACE_END